package com.ruoyi.system.service.h5.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.dto.AuthorizeDTO;
import com.ruoyi.system.domain.vo.WxAuthorizeVO;
import com.ruoyi.system.domain.vo.h5.MainSubjectVO;
import com.ruoyi.system.domain.vo.h5.SearchTips;
import com.ruoyi.system.domain.vo.h5.SearchVO;
import com.ruoyi.system.domain.vo.h5.UserStatisticsVO;
import com.ruoyi.system.service.IMiniStockService;
import com.ruoyi.system.service.IMiniSubjectService;
import com.ruoyi.system.service.MiniLoginLogService;
import com.ruoyi.system.service.MiniUserService;
import com.ruoyi.system.service.h5.IHomeService;
import com.ruoyi.system.service.h5.MiniSelfSelectionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.ruoyi.common.constant.Constants;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author :liding
 * @date : 2023/11/16 9:54
 */
@Service
@Slf4j
public class HomeServiceImpl implements IHomeService {
    @Autowired
    private IMiniSubjectService miniSubjectService;
    @Autowired
    private IMiniStockService miniStockService;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private MiniUserService miniUserService;
    @Autowired
    private MiniSelfSelectionService miniSelfSelectionService;
    @Autowired
    private MiniLoginLogService miniLoginLogService;
    @Autowired
    RedisCache redisCache;
    Cache<String, List<MainSubjectVO>> mtConfigCache = Caffeine.newBuilder()
            .maximumSize(100)
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .removalListener((key, value, cause) -> log.info("key:{},value:{},cause:{}", key, value, cause))
            .build();
    /**
     * 热点数据
     *
     * @return
     */
    @Override
    public AjaxResult hot() {
        List<MiniSubject> hotList = miniSubjectService.selectHotData();
        return AjaxResult.success(hotList);
    }

    /**
     * 微信认证
     *
     * @param params
     * @return
     */
    @Override
    public AjaxResult<WxAuthorizeVO> authorize(AuthorizeDTO params) {
        String code = params.getCode();
        String inviteCode = params.getInviteCode();
        WxAuthorizeVO vo = restTemplate.getForObject("https://api.weixin.qq.com/sns/jscode2session?appid=" + Constants.APP_ID + "&secret=" + Constants.SECRET + "&js_code=" + code + "&grant_type=authorization_code", WxAuthorizeVO.class);
        if (vo==null){
            return AjaxResult.error("调用微信授权接口失败");
        }
        String openid = vo.getOpenid();
        MiniUser user = miniUserService.getOne(Wrappers.<MiniUser>lambdaQuery().eq(MiniUser::getOpenid, openid));
        UserStatisticsVO userStatistics = new UserStatisticsVO();
        if (ObjectUtils.isNull(user)) {
            user = miniUserService.createUser(openid,inviteCode);
        }else{
            LocalDateTime now = LocalDateTime.now();
            miniUserService.update(Wrappers.<MiniUser>lambdaUpdate().set(MiniUser::getLastLoginTime, Timestamp.valueOf(now))
                    .eq(MiniUser::getId,user.getId()));
            List<MiniSelfSelection> selfSelectionCountList = miniSelfSelectionService.selectSelfSelectionCountByOpenid(openid);
            for (MiniSelfSelection selection : selfSelectionCountList) {
                if ("1".equals(selection.getType())){
                    userStatistics.setStockCount(selection.getCount());
                } else if ("2".equals(selection.getType())) {
                    userStatistics.setSubjectCount(selection.getCount());
                }
            }
            LocalDateTime registrationTime = user.getCreateTime().toLocalDateTime();
            Long activeCount = ChronoUnit.DAYS.between(registrationTime, now);
            userStatistics.setActiveCount(activeCount);
            if("88".equals(user.getVip())){
                if (user.getVipTime()!=null){
                    long vipRemain = ChronoUnit.DAYS.between(now, user.getVipTime().toLocalDateTime());
                    userStatistics.setVipRemain(vipRemain);
                    if (vipRemain<=0){
                        userStatistics.setVipRemain(0L);
                        user.setVip("0");
                        miniUserService.update(Wrappers.<MiniUser>lambdaUpdate().set(MiniUser::getVipFlag,0)
                                .eq(MiniUser::getId,user.getId()));

                    }
                }
            }
        }
        vo.setUserStatistics(userStatistics);
        vo.setUserInfo(user);
        redisCache.setCacheObject(openid,user,1, TimeUnit.DAYS);
        log.info("vo:"+ JSON.toJSONString(vo) );
        miniLoginLogService.save(new MiniLoginLog(user.getId(),user.getOpenid()));
        return AjaxResult.success(vo);
    }

    @Override
    public AjaxResult<SearchVO> search(String name) {
        if (StringUtils.isBlank(name)){
            return AjaxResult.success(new SearchVO());
        }
        List<SearchTips> tips = new ArrayList<>();
        List<MiniSubject> subjectList = miniSubjectService.list(Wrappers.<MiniSubject>lambdaQuery().select(MiniSubject::getSubjectId, MiniSubject::getName)
                .eq(MiniSubject::getStatus, 0)
                .eq(MiniSubject::getDelFlag, 0)
                .like(MiniSubject::getName, name)
                .orderByAsc(MiniSubject::getOrderNum));
        subjectList.forEach(it ->tips.add(new SearchTips(2,it.getSubjectId(),it.getName(),null)));
        List<MiniStock> stockList = miniStockService.list(Wrappers.<MiniStock>lambdaQuery()
                .select(MiniStock::getId, MiniStock::getName, MiniStock::getStockNo)
                .eq(MiniStock::getDeleted, 0)
                .like(MiniStock::getName, name)
                .orderByAsc(MiniStock::getSort));
        stockList.forEach(it ->tips.add(new SearchTips(1,it.getId(),it.getName(),it.getStockNo())));
        return AjaxResult.success(new SearchVO(subjectList,stockList, tips));
    }

    @Override
    public AjaxResult<List<MiniSubject>> hot2() {
        List<MiniSubject> hotList = miniSubjectService.selectHot2Data();
        int size = hotList.size();
        for (int i = 0; i < size; i++) {
            if (i<5){
                hotList.get(i).setFlag("沸");
            }else{
                hotList.get(i).setFlag("热");
            }
        }
        return AjaxResult.success(hotList);
    }

    @Override
    public AjaxResult<List<MainSubjectVO>> mainSubject() {
        List<MainSubjectVO> main = mtConfigCache.get("main",o->miniSubjectService.mainSubject());
        return AjaxResult.success(main);
    }

    @Override
    public void refreshMainSubject() {
        mtConfigCache.put("main",miniSubjectService.mainSubject());
    }
}
